﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RestSharp;
using RestSharp.Deserializers;
using System.Security.Cryptography;

namespace BoxcarProviderClient
{
    class BoxcarNotifier
    {
        string _baseUrl = "http://boxcar.io/devices/providers/";
        string _boxCarEmailAddress;
        string _apiKey;
        string _apiSecret;
        string _boxCarPassword;
        string _sentFrom;
        string _message;
        string _sourceUrl;
        string _iconUrl = "http://goo.gl/wtS1S";
        string _soundName;
        int _uniqueId = -1;

        RestResponse _restResponse;

        //constructor
        public BoxcarNotifier(string apikey, string secret, string email, string password, string message)
        {
            _uniqueId = Environment.TickCount; //used as a integer to avoid duplicated notifications (optional)
            _apiKey = apikey;
            _apiSecret = secret;
            _boxCarEmailAddress = email;
            _boxCarPassword = password;
            _message = message;
            _soundName = "Boing"; //must be a valid sound byte in the boxcar app, if not found it plays default sound
            _sentFrom = "[Your Provider Name]";
        }

        /// <summary>
        ///*Subscribes a new user*
        ///This methos takes a user's Boxcar email, MD5 hashes it and subscribes them to this provider
        ///The result is a notification to this Boxcar user's mobile device as a request to add this provider as a servicem
        ///POST URL: http://boxcar.io/devices/providers/_apiKey/notifications/subscribe
        ///Returns: HTTP Status code 404 if Boxcar is unable to find the registered user by email in their system
        /// </summary>
        /// <returns>RestResponse</returns>
         public RestResponse notifySubscriber()
        {
            var client = new RestClient(_baseUrl + _apiKey + "/notifications/subscribe");
            var request = new RestRequest(Method.POST);

            //only requires one parameter to be sent
            request.AddParameter("email", calculateMd5Hash(_boxCarEmailAddress)); //take the email and get the MD5hash

            //execute the request
            _restResponse = client.Execute(request);
            return _restResponse;
        }

         ///<summary>
         ///Sends a notification to an individual subscriber
         ///POST URL: http://boxcar.io/devices/providers/_apiKey/notifications/
         ///</summary>
         ///<returns>RestResponse</returns> 
        public RestResponse notifyIndividual()
        {
            var client = new RestClient(_baseUrl + _apiKey + "/notifications");
            var request = new RestRequest(Method.POST);

            request.AddParameter("email", calculateMd5Hash(_boxCarEmailAddress)); //the subscribers MD5'd eamil address
            request.AddParameter("notification[from_screen_name]", _sentFrom); //required
            request.AddParameter("notification[message]", _message); //required
            request.AddParameter("notification[from_remote_service_id]", _uniqueId); //optional
            request.AddParameter("notification[icon_url]", _iconUrl); //optional
            request.AddParameter("notification[sound]", _soundName); //optional

            //execute the request
            _restResponse = client.Execute(request);
            return _restResponse;
        }

        ///<summary>
        ///Sends a broadcast message to *ALL* subscribers
        ///POST URL: http://boxcar.io/devices/providers/_apiKey/notifications/broadcast
        ///</summary>
        ///<returns>RestResponse</returns> 
         public RestResponse notifyBroadcast()
        {
            var client = new RestClient(_baseUrl + _apiKey + "/notifications/broadcast");
            var request = new RestRequest(Method.POST);

            request.AddParameter("secret", _apiSecret);
            request.AddParameter("notification[from_screen_name]", _sentFrom);
            request.AddParameter("notification[message]", _message);
            request.AddParameter("notification[from_remote_servie_id]", _uniqueId); //this should be a unique int to avoid duplication
            request.AddParameter("notification[icon_url]", _iconUrl); //icon you want the user to see in the alert

            //execute the request
            _restResponse = client.Execute(request);
            return _restResponse;
        }

        ///<summary>
        ///Sends yourself a notification using the Growl or API service
        ///API reference: http://help.boxcar.io/kb/developers/sending-yourself-notifications
        ///To send yourself notifications, Boxcar requires that you ADD the growl service in your app.  
        ///</summary>
         ///<returns>RestResponse</returns> 
        public RestResponse notifySelf()
        {
            var client = new RestClient("https://boxcar.io/notifications/");
            client.Authenticator = new HttpBasicAuthenticator(_boxCarEmailAddress, _boxCarPassword);
            var request = new RestRequest(Method.POST);

            //available parameters sent to Boxcar
            request.AddParameter("notification[from_screen_name]", "[Your Name]");
            request.AddParameter("notification[message]", _message);
            request.AddParameter("notification[from_remote_servie_id]", _uniqueId); //id should be unique to avoid duplication
            request.AddParameter("notification[source_url]", _sourceUrl);
            request.AddParameter("notification[icon_url]", _iconUrl);
            request.AddParameter("notification[sound]", _soundName); //the sound name must match an available sound name in the Boxcar app
            
            //execute the request
            _restResponse = client.Execute(request);
            return _restResponse;
        }

        //This entire method taken from http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5.aspx
        //Hash an input string and return the hash as a 32 character hexadecimal string.
        static string calculateMd5Hash(string emailAccount)
        {
            // Create a new instance of the MD5CryptoServiceProvider object.
            MD5 md5Hasher = MD5.Create();

            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(emailAccount));

            // Create a new Stringbuilder to collect the bytes and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data 
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
            return sBuilder.ToString();
        }
    }
}
